package com.lyzml.dlna;

import android.util.Log;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lyzml.dlna.manager.DLNADeviceManager;
import com.lyzml.dlna.player.control.IController;
import com.lyzml.dlna.player.control.MultiPointController;
import com.taobao.weex.WXSDKEngine;
import com.taobao.weex.annotation.JSMethod;
import com.taobao.weex.bridge.JSCallback;

import org.cybergarage.upnp.Device;
import org.cybergarage.util.StringUtil;
import org.cybergarage.xml.parser.JaxpParser;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.List;

import io.dcloud.feature.uniapp.annotation.UniJSMethod;
import io.dcloud.feature.uniapp.bridge.UniJSCallback;
import io.dcloud.feature.uniapp.common.UniDestroyableModule;

public class LyzmlDLNAWXModule extends UniDestroyableModule {

    private IController mController;

    /**
     * 开始搜索
     *
     * @param jsCallback
     */
    @UniJSMethod(uiThread = true)
    public void startSearch(final UniJSCallback jsCallback) {
        DLNADeviceManager.getInstance().stopDiscovery();
        DLNADeviceManager.getInstance().startDiscovery(new DLNADeviceManager.MediaRenderDeviceChangeListener() {
            @Override
            public void onStarted() {
                Log.d("==LyzmlDLNAModule==", "startSearch onStarted");
                JSONObject retObj = new JSONObject();
                retObj.put("code", 0);
                retObj.put("desc", "search started!");
                jsCallback.invokeAndKeepAlive(retObj);
            }

            @Override
            public void onDeviceListChanged(List<Device> devList) {
                Log.d("==LyzmlDLNAModule==", "startSearch onDeviceListChanged");
                JSONArray devArr = new JSONArray();
                for (int i = 0; i < devList.size(); i++) {
                    Device dev = devList.get(i);
                    JSONObject devObj = new JSONObject();
                    devObj.put("ip", getLocalIp(dev.getURLBase()));
                    devObj.put("name", dev.getFriendlyName());
                    devObj.put("udn", dev.getUDN());
                    devArr.add(devObj);
                }
                JSONObject retObj = new JSONObject();
                retObj.put("code", 1);
                retObj.put("desc", "search result change!");
                retObj.put("result", devArr);
                jsCallback.invokeAndKeepAlive(retObj);
            }

            @Override
            public void onFinished() {
                Log.d("==LyzmlDLNAModule==", "startSearch onFinished");
                JSONObject retObj = new JSONObject();
                retObj.put("code", 2);
                retObj.put("desc", "search finished!");
                jsCallback.invokeAndKeepAlive(retObj);
            }
        });
    }

    /**
     * 获取搜索结果
     */
    @UniJSMethod(uiThread = true)
    public void getSearchResult(UniJSCallback jsCallback) {
        List<Device> devList = DLNADeviceManager.getInstance().getSearchResult();
        JSONArray retArr = new JSONArray();
        if (devList != null && devList.size() > 0) {
            for (int i = 0; i < devList.size(); i++) {
                Device dev = devList.get(i);
                JSONObject retObj = new JSONObject();
//                retObj.put("ip", dev.getInterfaceAddress());
                retObj.put("ip", getLocalIp(dev.getURLBase()));
                retObj.put("name", dev.getFriendlyName());
                retObj.put("udn", dev.getUDN());
                retArr.add(retObj);
            }
        }
        jsCallback.invoke(retArr);
    }

    /**
     * 播放视频
     *
     * @param params
     */
    @UniJSMethod(uiThread = true)
    public void playVideo(JSONObject params, UniJSCallback jsCallback) {
        JSONObject retObj = new JSONObject();
//        String devIP = params.getString("ip");
        String devUdn = params.getString("udn");
        String mediaURL = params.getString("mediaURL");
        if (devUdn != null && devUdn.length() > 0 && mediaURL != null && mediaURL.length() > 0) {
            if (mController == null) {
                mController = new MultiPointController();
            }
            Device currDevice = DLNADeviceManager.getInstance().getCurrentDevice();
            if (null == currDevice || !devUdn.equals(currDevice.getUDN())) {
                List<Device> devList = DLNADeviceManager.getInstance().getSearchResult();
                if (devList != null && devList.size() > 0) {
                    for (int i = 0; i < devList.size(); i++) {
                        Device dev = devList.get(i);
                        if (dev.getUDN().equals(devUdn)) {
                            DLNADeviceManager.getInstance().setCurrentDevice(dev);
                            break;
                        }
                    }
                } else {
                    retObj.put("code", 1);
                    retObj.put("desc", "设备不存在，请重新搜索");
                }
            }
            currDevice = DLNADeviceManager.getInstance().getCurrentDevice();
            if (null != currDevice) {
                mController.play(currDevice, mediaURL);
                retObj.put("code", 0);
                retObj.put("desc", "播放成功");
            } else {
                retObj.put("code", 1);
                retObj.put("desc", "设备连接失败");
            }
        } else {
            retObj.put("code", 1);
            retObj.put("desc", "参数错误");
        }
        jsCallback.invoke(retObj);
    }

    /**
     * 停止播放视频
     */
    @UniJSMethod(uiThread = true)
    public void pauseVideo() {
        Device currDevice = DLNADeviceManager.getInstance().getCurrentDevice();
        if (currDevice != null && mController != null) {
            mController.pause(currDevice);
        }
    }

    /**
     * 停止播放视频
     */
    @UniJSMethod(uiThread = true)
    public void resumeVideo(int pauseTimeSeconds) {
        Device currDevice = DLNADeviceManager.getInstance().getCurrentDevice();
        if (currDevice != null && mController != null) {
            mController.resume(currDevice,pauseTimeSeconds);
        }
    }

    /**
     * 停止播放视频
     */
    @UniJSMethod(uiThread = true)
    public void stopVideo() {
        Device currDevice = DLNADeviceManager.getInstance().getCurrentDevice();
        if (currDevice != null && mController != null) {
            mController.stop(currDevice);
        }
    }

    /**
     * @return String
     * @Title: getIpAddress
     * @Description: 获取设备ip地址
     */
    @UniJSMethod(uiThread = true)
    public void getIpAddress(UniJSCallback jsCallback) {
        String ipAddr = "";
        try {
            for (Enumeration<NetworkInterface> enNetI = NetworkInterface.getNetworkInterfaces(); enNetI.hasMoreElements(); ) {
                NetworkInterface netI = enNetI.nextElement();
                for (Enumeration<InetAddress> enumIpAddr = netI.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    if (inetAddress instanceof Inet4Address && !inetAddress.isLoopbackAddress()) {
                        ipAddr = inetAddress.getHostAddress();
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        jsCallback.invoke(ipAddr);
    }

    @UniJSMethod(uiThread = true)
    public void setPlayMonitor(UniJSCallback jsCallback) {
        if (mController == null) {
            mController = new MultiPointController();
        }
        mController.setPlayMonitor(new IController.PlayerMonitor() {
            @Override
            public void onPreparing() {
                JSONObject retObj = new JSONObject();
                retObj.put("code", 0);
                retObj.put("desc", "onPreparing");
                jsCallback.invokeAndKeepAlive(retObj);
            }

            @Override
            public void onGetTransportState(String state) {
                JSONObject retObj = new JSONObject();
                retObj.put("code", 1);
                retObj.put("desc", "onGetTransportState");
                retObj.put("result", state);
                jsCallback.invokeAndKeepAlive(retObj);
            }

            @Override
            public void onGetMediaDuration(int totalTimeSeconds) {
                JSONObject retObj = new JSONObject();
                retObj.put("code", 2);
                retObj.put("desc", "onGetMediaDuration");
                retObj.put("result", totalTimeSeconds);
                jsCallback.invokeAndKeepAlive(retObj);
            }

            @Override
            public void onPlay() {
                JSONObject retObj = new JSONObject();
                retObj.put("code", 3);
                retObj.put("desc", "onPlay");
                jsCallback.invokeAndKeepAlive(retObj);
            }

            @Override
            public void onPause() {
                JSONObject retObj = new JSONObject();
                retObj.put("code", 4);
                retObj.put("desc", "onPause");
                jsCallback.invokeAndKeepAlive(retObj);
            }

            @Override
            public void onStop() {
                JSONObject retObj = new JSONObject();
                retObj.put("code", 5);
                retObj.put("desc", "onStop");
                jsCallback.invokeAndKeepAlive(retObj);
            }

            @Override
            public void onVolumeChanged(int current) {
                JSONObject retObj = new JSONObject();
                retObj.put("code", 6);
                retObj.put("desc", "onVolumeChanged");
                retObj.put("result", current);
                jsCallback.invokeAndKeepAlive(retObj);
            }

            @Override
            public void onProgressUpdated(int currentTimeSeconds) {
                JSONObject retObj = new JSONObject();
                retObj.put("code",7);
                retObj.put("desc", "onProgressUpdated");
                retObj.put("result", currentTimeSeconds);
                jsCallback.invokeAndKeepAlive(retObj);
            }

            @Override
            public void onSeekComplete() {
                JSONObject retObj = new JSONObject();
                retObj.put("code", 8);
                retObj.put("desc", "onSeekComplete");
                jsCallback.invokeAndKeepAlive(retObj);
            }

            @Override
            public void onError(String msg) {
                JSONObject retObj = new JSONObject();
                retObj.put("code", 9);
                retObj.put("desc", "onError");
                retObj.put("result", msg);
                jsCallback.invokeAndKeepAlive(retObj);
            }

            @Override
            public void onMuteStatusChanged(boolean mute) {
                JSONObject retObj = new JSONObject();
                retObj.put("code", 10);
                retObj.put("desc", "onMuteStatusChanged");
                retObj.put("result", mute);
                jsCallback.invokeAndKeepAlive(retObj);
            }

            @Override
            public void onComplete() {
                JSONObject retObj = new JSONObject();
                retObj.put("code", 11);
                retObj.put("desc", "onComplete");
                jsCallback.invokeAndKeepAlive(retObj);
            }

            @Override
            public void onPlayItemChanged() {
                JSONObject retObj = new JSONObject();
                retObj.put("code", 12);
                retObj.put("desc", "onPlayItemChanged");
                jsCallback.invokeAndKeepAlive(retObj);
            }

            @Override
            public void onGetMaxVolume(int max) {
                JSONObject retObj = new JSONObject();
                retObj.put("code", 13);
                retObj.put("desc", "onGetMaxVolume");
                retObj.put("result", max);
                jsCallback.invokeAndKeepAlive(retObj);
            }

        });
    }

    @UniJSMethod(uiThread = true)
    public void isPlaying(UniJSCallback jsCallback) {
        if (mController != null) {
            jsCallback.invoke(mController.isPlaying());
        } else {
            jsCallback.invoke(false);
        }
    }

    @UniJSMethod(uiThread = true)
    public void seek(int toSeconds) {
        if (mController != null) {
            Device device = DLNADeviceManager.getInstance().getCurrentDevice();
            if (device != null) {
                mController.seek(device, toSeconds);
            }
        }
    }

    @UniJSMethod(uiThread = true)
    public void setMute(boolean mute) {
        if (mController != null) {
            Device device = DLNADeviceManager.getInstance().getCurrentDevice();
            if (device != null) {
                mController.setMute(device, mute);
            }
        }
    }

    @UniJSMethod(uiThread = true)
    public void getVolume() {
        if (mController != null) {
            Device device = DLNADeviceManager.getInstance().getCurrentDevice();
            if (device != null) {
                mController.getVolume(device);
            }
        }
    }

//    @UniJSMethod(uiThread = true)
//    public void getMinVolumeValue() {
//        if (mController != null) {
//            Device device = DLNADeviceManager.getInstance().getCurrentDevice();
//            if (device != null) {
//                mController.getMinVolumeValue(device);
//            }
//        }
//    }

//    @UniJSMethod(uiThread = true)
//    public void getMaxVolumeValue() {
//        if (mController != null) {
//            Device device = DLNADeviceManager.getInstance().getCurrentDevice();
//            if (device != null) {
//                mController.getMaxVolumeValue(device);
//            }
//        }
//    }

    @UniJSMethod(uiThread = true)
    public void setVolume(int volume) {
        if (mController != null) {
            Device device = DLNADeviceManager.getInstance().getCurrentDevice();
            if (device != null) {
                mController.setVolume(device, volume);
            }
        }
    }

    @UniJSMethod(uiThread = true)
    public void getMediaDuration() {
        if (mController != null) {
            Device device = DLNADeviceManager.getInstance().getCurrentDevice();
            if (device != null) {
                mController.getMediaDuration(device);
            }
        }
    }

    @UniJSMethod(uiThread = true)
    public void getPositionInfo() {
        if (mController != null) {
            Device device = DLNADeviceManager.getInstance().getCurrentDevice();
            if (device != null) {
                mController.getPositionInfo(device);
            }
        }
    }

    @UniJSMethod(uiThread = true)
    public void getTransportState() {
        if (mController != null) {
            Device device = DLNADeviceManager.getInstance().getCurrentDevice();
            if (device != null) {
                mController.getTransportState(device);
            }
        }
    }

    @Override
    public void destroy() {
        DLNADeviceManager.getInstance().stopDiscovery();
    }


    private String getLocalIp(String ipStr) {
        if (ipStr != null && ipStr.length() > 0) {
            ipStr = ipStr.replaceAll("http://", "").replaceAll("https://", "");
            int idx = ipStr.indexOf(":");
            if (idx >= 0) {
                ipStr = ipStr.substring(0, idx);
            }
        }
        return ipStr;
    }
}
